package com.tabjin.rfidsocket.service.access.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.tabjin.rfidsocket.common.org.n3r.idworker.Sid;
import com.tabjin.rfidsocket.common.utils.BeanValidator;
import com.tabjin.rfidsocket.common.utils.PagedGridResult;
import com.tabjin.rfidsocket.exception.ParamException;
import com.tabjin.rfidsocket.mapper.mapper.ArchProjectMapper;
import com.tabjin.rfidsocket.mapper.mapper.ArchProjectBuildingUserMapper;
import com.tabjin.rfidsocket.pojo.*;
import com.tabjin.rfidsocket.pojo.bo.access.ArchProjectBO;
import com.tabjin.rfidsocket.pojo.vo.access.ArchProjectVO;
import com.tabjin.rfidsocket.service.access.ArchProjectService;
import com.tabjin.rfidsocket.service.sys.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author tabjin
 * create at 2021/1/11 14:14
 * @program rfid_socket
 * @description
 */
@Service
public class ArchProjectServiceImpl implements ArchProjectService {

    static final Logger logger = LoggerFactory.getLogger(ArchProjectServiceImpl.class);

    private final ArchProjectMapper archProjectMapper;
    private final Sid sid;
    private final ArchProjectBuildingUserMapper archProjectBuildingUserMapper;
    private final SysUserService sysUserService;

    public ArchProjectServiceImpl(ArchProjectMapper archProjectMapper, Sid sid, ArchProjectBuildingUserMapper archProjectBuildingUserMapper, SysUserService sysUserService) {
        this.archProjectMapper = archProjectMapper;
        this.sid = sid;
        this.archProjectBuildingUserMapper = archProjectBuildingUserMapper;
        this.sysUserService = sysUserService;
    }

    /**
     * 添加项目
     *
     * @return
     */
    @Override
    public ArchProjectVO add(ArchProjectBO bo) {
        BeanValidator.check(bo);
        if (checkExist(bo.getName())) {
            logger.error("新增项目 已存在相同的项目名");
            throw new ParamException("新增项目 已存在相同的项目名");
        }

        ArchProject archProject = ArchProject.builder()
//                .id(sid.nextShort())
                .name(bo.getName())
                .province(bo.getProvince())
                .city(bo.getCity())
                .district(bo.getDistrict())
                .street(bo.getStreet())
                .age(bo.getAge())
                .unitNature(bo.getUnitNature())
                .type(bo.getType())
                .longitude(bo.getLongitude())
                .latitude(bo.getLatitude())
                .address(bo.getAddress())
                .standardAddressCoding(bo.getStandardAddressCoding())
                .standardProjectCode(bo.getStandardProjectCode())
                .propertyProjectManager(bo.getPropertyProjectManager())
                .propertyContactNumber(bo.getPropertyContactNumber())
                .startTime(bo.getStartTime())
                .completionTime(bo.getCompletionTime())
                .propertyContractStartTime(bo.getPropertyContractStartTime())
                .propertyContractExpireTime(bo.getPropertyContractExpireTime())
                .propertyAcquisitionMethod(bo.getPropertyAcquisitionMethod())
                .archProjectInfrastructureId(bo.getArchProjectInfrastructureId())
                .archDeveloperId(bo.getArchDeveloperId())
                .archPropertyManagementOfficeAreaId(bo.getArchPropertyManagementOfficeAreaId())
                .repairResidentialMoney(bo.getRepairResidentialMoney())
                .repairCommercialMoney(bo.getRepairCommercialMoney())
                .build();

        archProject.setCreateTime(new Date());
        archProject.setUpdateTime(new Date());

        // TODO 由于门禁权限这边权限没有打开，暂时直接写死
        archProject.setOperator("张进");
//        archProject.setOperator(RequestHolder.getCurrentUser().getUsername());
        archProject.setOperatorIp("127.0.0.1");


        archProjectMapper.insertSelective(archProject);
        ArchProjectVO vo = new ArchProjectVO();
        BeanUtils.copyProperties(archProject, vo);
        return vo;
    }

    /**
     * 更新项目
     *
     * @param bo
     * @return ArchProject
     */
    @Override
    public ArchProjectVO update(ArchProjectBO bo) {
        Preconditions.checkNotNull(bo.getId(), "项目id为空");

        ArchProject before = archProjectMapper.selectByPrimaryKey(bo.getId());
        Preconditions.checkNotNull(before, "待更新的项目为空");

        ArchProject after = ArchProject.builder()
                .id(bo.getId())
                .name(bo.getName())
                .province(bo.getProvince())
                .city(bo.getCity())
                .district(bo.getDistrict())
                .street(bo.getStreet())
                .age(bo.getAge())
                .unitNature(bo.getUnitNature())
                .type(bo.getType())
                .longitude(bo.getLongitude())
                .latitude(bo.getLatitude())
                .address(bo.getAddress())
                .standardAddressCoding(bo.getStandardAddressCoding())
                .standardProjectCode(bo.getStandardProjectCode())
                .propertyProjectManager(bo.getPropertyProjectManager())
                .propertyContactNumber(bo.getPropertyContactNumber())
                .startTime(bo.getStartTime())
                .completionTime(bo.getCompletionTime())
                .propertyContractStartTime(bo.getPropertyContractStartTime())
                .propertyContractExpireTime(bo.getPropertyContractExpireTime())
                .propertyAcquisitionMethod(bo.getPropertyAcquisitionMethod())
                .archProjectInfrastructureId(bo.getArchProjectInfrastructureId())
                .archDeveloperId(bo.getArchDeveloperId())
                .archPropertyManagementOfficeAreaId(bo.getArchPropertyManagementOfficeAreaId())
                .repairResidentialMoney(bo.getRepairResidentialMoney())
                .repairCommercialMoney(bo.getRepairCommercialMoney())
                .createTime(bo.getCreateTime())
                .build();


        after.setOperatorIp("127.0.0.1");
        after.setUpdateTime(new Date());
        // TODO 由于门禁权限这边权限没有打开，暂时直接写死
//        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperator("张进");

        archProjectMapper.updateByPrimaryKeySelective(after);

        ArchProjectVO vo = new ArchProjectVO();
        BeanUtils.copyProperties(after, vo);
        return vo;
    }

    /**
     * 删除项目(软)
     *
     * @param id 项目id
     * @return
     */
    @Override
    public ArchProject delete(Integer id) {
        Preconditions.checkNotNull(id, "待删除的项目id为空");
        Optional<ArchProject> archProjectOptional = Optional.ofNullable(archProjectMapper.selectByPrimaryKey(id));
        ArchProject archProjectBefore = archProjectOptional.orElseThrow(() -> new ParamException("无待删除的项目"));

        // 更新删除时间
        archProjectBefore.setDeleteTime(new Date());
        archProjectBefore.setType(0);

        archProjectMapper.updateByPrimaryKeySelective(archProjectBefore);
        return archProjectBefore;
    }

    /**
     * 获取项目详情
     *
     * @param projectId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public ArchProjectVO getEachProject(Integer projectId) {
        Preconditions.checkNotNull(projectId, "项目id为空");
        ArchProject archProject = archProjectMapper.selectByPrimaryKey(projectId);
        Preconditions.checkNotNull(archProject, "获取的项目为空");
        ArchProjectVO vo = new ArchProjectVO();
        BeanUtils.copyProperties(archProject, vo);
        return vo;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Optional<List<ArchProject>> getProjectByManagerId(Integer managerId) {
        Example example = new Example(ArchProject.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("managerId", managerId);
        List<ArchProject> archProjects = archProjectMapper.selectByExample(example);
        Optional<List<ArchProject>> archProjectsOptional = Optional.ofNullable(archProjects);
        return archProjectsOptional;
    }

    /**
     * 根据县区获取项目
     *
     * @param region
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Optional<List<ArchProject>> getProjectsByRegion(String region) {
        if (StringUtils.isBlank(region)) {
            throw new ParamException("无地区");
        }
        Example example = new Example(ArchProject.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("district", region);
        Optional<List<ArchProject>> archProjects = Optional.ofNullable(archProjectMapper.selectByExample(example));
        return archProjects;
    }

    @Override
    public PagedGridResult projectsFilter(Integer page, Integer pageSize, String province, String city, String projectName) {
        PageHelper.startPage(page, pageSize);

        // 获取项目数据
        Example example = new Example(ArchProject.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("province", province);
        criteria.andEqualTo("city", city);
        if (!StringUtils.isBlank(projectName)) {
            criteria.andLike("name", projectName);
        }
        Optional<List<ArchProject>> archProjectsOptional = Optional.ofNullable(archProjectMapper.selectByExample(example));
        List<ArchProject> archProjectList = archProjectsOptional.orElseThrow(() -> new ParamException("项目不存在"));
        return setPagesGrid(archProjectList, page);
    }

    @Override
    public Optional<List<ArchProjectBuildingUser>> getProjectIdByUserId(Integer userId) {
        Preconditions.checkNotNull(userId, "userId空");
        Example example = new Example(ArchProjectBuildingUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userId", userId);
        List<ArchProjectBuildingUser> archProjectBuildingUsers = archProjectBuildingUserMapper.selectByExample(example);
        Optional<List<ArchProjectBuildingUser>> archProjectBuildingUsersOptional = Optional.ofNullable(archProjectBuildingUsers);
        return archProjectBuildingUsersOptional;
    }

    /**
     * 获取所有项目
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult getAll(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<ArchProject> archProjectList = archProjectMapper.selectAll();

        List<ArchProjectVO> archProjectVOList = archProjectList.stream().map(archProject -> {
            ArchProjectVO vo = new ArchProjectVO();
            BeanUtils.copyProperties(archProject, vo);
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            vo.setCreateTimeFormat(df.format(vo.getCreateTime()));
            return vo;
        }).collect(Collectors.toList());

        return setPagesGrid(archProjectVOList, page);
    }

    /**
     * 获取项目基础设施
     *
     * @param archProjectInfrastructureId 项目基础设施id
     * @return
     */
    @Override
    public List<ArchProjectInfrastructure> getArchProjectInfrastructure(Integer archProjectInfrastructureId) {
        return null;
    }

    /**
     * 获取开发商
     *
     * @param archDeveloperId 开发商id
     * @return
     */
    @Override
    public List<ArchDeveloper> getArchDeveloper(Integer archDeveloperId) {
        return null;
    }

    /**
     * 获取物管办公区域
     *
     * @param archPropertyManagementOfficeAreaId 物管办公区域id
     * @return
     */
    @Override
    public List<ArchPropertyManagementOfficeArea> getArchPropertyManagementOfficeArea(Integer archPropertyManagementOfficeAreaId) {
        return null;
    }

    /**
     * 判断项目是否存在
     *
     * @param projectName
     * @return
     */
    private boolean checkExist(String projectName) {
        Example example = new Example(ArchProject.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", projectName);
        return archProjectMapper.selectCountByExample(example) > 0;
    }

    /**
     * 封装分页助手
     *
     * @param list
     * @param page
     * @return
     */
    private PagedGridResult setPagesGrid(List<?> list, Integer page) {
        PageInfo pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;
    }
}
